/* Copyright (c) 2010, Iain Wade <iwade@optusnet.com.au>
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __PSAN_WIREFORMAT_H__
#define __PSAN_WIREFORMAT_H__

#include <netinet/in.h>

#define PSAN_PORT 20001

#define PSAN_ERROR 0x05
#define PSAN_FIND 0x0d
#define PSAN_FIND_RESPONSE 0x0e
#define PSAN_RESOLVE 0x0f
#define PSAN_RESOLVE_RESPONSE 0x10
#define PSAN_IDENTIFY 0x13
#define PSAN_GET 0x00
#define PSAN_GET_RESPONSE 0x11
#define PSAN_PUT 0x01
#define PSAN_PUT_RESPONSE 0x04

struct psan_ctrl_t {
    uint8_t cmd;
    uint8_t len_power;
    uint16_t seq;
} __attribute__((__packed__));

struct psan_find_t {
    struct psan_ctrl_t ctrl;
} __attribute__((__packed__));

struct psan_find_response_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[12];
    struct in_addr ip4;
} __attribute__((__packed__));

struct psan_resolve_t {
    struct psan_ctrl_t ctrl;
    char id[64];
} __attribute__((__packed__));

struct psan_resolve_response_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[76];
    struct in_addr ip4;
    uint8_t unknown2[20];
} __attribute__((__packed__));

struct psan_identify_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[24];
} __attribute__((__packed__));

struct psan_get_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[12];
    struct in_addr ip4;
    uint8_t unknown2[2];
    uint32_t sector;
    uint8_t unknown3;
    uint8_t info;
} __attribute__((__packed__));

struct psan_get_response_t {
    struct psan_get_t get;
    uint8_t buffer[];
} __attribute__((__packed__));

struct psan_get_response_disk_t {
    char version[16];
    uint8_t market_class[2];
    uint8_t manufacturer_code[3];
    uint8_t part_number[3];
    uint8_t sector_total[6];
    uint8_t sector_free[6];
    uint8_t unknown1[5];
    uint8_t partitions;
    uint8_t unknown2[4];
    char label[56]; // UI indicates 28-chars max - chars stored as UTF16
    uint8_t unknown3[410];
} __attribute__((__packed__));

struct psan_get_response_partition_t {
    uint8_t unknown1[6];
    char label[28];
    uint8_t unknown2[100];
    uint8_t sector_size[6];
    uint8_t unknown3[38];
    char id[64];
    uint8_t unknown4[270];
} __attribute__((__packed__));

struct psan_put_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[12];
    struct in_addr ip4;
    uint8_t unknown2[2];
    uint32_t sector;
    uint8_t unknown3;
    uint8_t info;
    uint8_t buffer[];
} __attribute__((__packed__));

struct psan_put_response_t {
    struct psan_ctrl_t ctrl;
    uint8_t unknown1[12];
    struct in_addr ip4;
    uint8_t unknown2[2];
    uint32_t sector;
    uint8_t unknown3;
    uint8_t info;
} __attribute__((__packed__));

#endif /* __PSAN_WIREFORMAT_H__ */
